package com.xd.common.smsLogin;

import com.xd.common.exception.XkdException;
import com.xd.core.system.service.H5MyUserDetailsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class H5MobilecodeAuthenticationProvider implements AuthenticationProvider {

    private H5MyUserDetailsService h5MyUserDetailsService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    private static final String h5loginCodeError = "h5loginCodeError:";
    private static final String h5loginCode = "h5loginCode:";


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        H5MobilecodeAuthenticationToken h5MobilecodeAuthenticationToken = (H5MobilecodeAuthenticationToken) authentication;
        String phone = h5MobilecodeAuthenticationToken.getPhone();
        String mobileCode = h5MobilecodeAuthenticationToken.getMobileCode();

        // 从redis中读取手机号对应的验证码及其用户名
        String code = (String) redisTemplate.opsForValue().get(h5loginCode+phone);
        // 判断验证码是否一致

        if (StringUtils.isEmpty(code)){
            throw new XkdException("验证码失效");
        }
        if (!mobileCode.equals(code)) {
            //判断验证码如果5分钟内错误5次则删除验证码
            Integer errorCount = (Integer) redisTemplate.opsForValue().get(h5loginCodeError+phone);
            if (errorCount == null){
                redisTemplate.opsForValue().set(h5loginCodeError+phone,1,5, TimeUnit.MINUTES);
            }else {
                if (errorCount >= 5){
                    redisTemplate.delete(h5loginCode+phone);
                    redisTemplate.delete(h5loginCodeError+phone);
                }else {
                    redisTemplate.opsForValue().increment(h5loginCodeError+phone,1);
                }
            }
            throw new XkdException("验证码错误");
        }

        // 如果验证码一致，从数据库中读取该手机号对应的用户信息
        UserDetails loadedUser = h5MyUserDetailsService.loadUserByUsername(phone);
        if (loadedUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        } else {
            return new H5MobilecodeAuthenticationToken(loadedUser, null, loadedUser.getAuthorities());
        }
    }


    @Override
    public boolean supports(Class<?> aClass) {
        return H5MobilecodeAuthenticationToken.class.isAssignableFrom(aClass);
    }

    public void setUserDetailsService(H5MyUserDetailsService h5MyUserDetailsService) {
        this.h5MyUserDetailsService = h5MyUserDetailsService;
    }
}